#include "head.h"
#include <fcntl.h>           /* Definition of AT_* constants */
#include <sys/stat.h>
#include "time.h"
#include <stdbool.h>


extern int lstat(const char *,struct stat*);
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);

int fileDetail(const char *path)
{
    if(!path){
ERROR:
        DEBUG_MSG();
        perror("error!");
        return -1;

    }
    struct stat sbuf;
    // int r= stat(path,&sbuf);
    int r= lstat(path,&sbuf);
    if(r==-1){
        goto ERROR;
    }
    char buf[11];
    buf[10]=0;
    memset(buf,0,sizeof(buf));
    // switch (sbuf.st_mode & __S_IFMT) {
    // case __S_IFBLK:  printf("block device\n");            break;
    // case __S_IFCHR:  printf("character device\n");        break;
    // case __S_IFDIR:  printf("directory\n");               break;
    // case __S_IFIFO:  printf("FIFO/pipe\n");               break;
    // case __S_IFLNK:  printf("symlink\n");                 break;
    // case __S_IFREG:  printf("regular file\n");            break;
    // case __S_IFSOCK: printf("socket\n");                  break;
    // default:       printf("unknown?\n");                break;
    // }
    if(S_ISDIR(sbuf.st_mode)){
        buf[0]='d';
    }
    else  if(S_ISLNK(sbuf.st_mode)){
        buf[0]='l';
    }
    else  if(S_ISREG(sbuf.st_mode)){
        buf[0]='-';
    }
    else  if(S_ISFIFO(sbuf.st_mode)){
        buf[0]='p';
    }
    else  if(S_ISBLK(sbuf.st_mode)){
        buf[0]='b';
    }
    else  if(S_ISCHR(sbuf.st_mode)){
        buf[0]='c';
    }
    
    buf[1] = (sbuf.st_mode& S_IRUSR)?'r':'-';
    buf[2] = (sbuf.st_mode& S_IWUSR)?'w':'-';
    buf[3] = (sbuf.st_mode& S_IXUSR)?'x':'-';

    buf[4] = (sbuf.st_mode& S_IRGRP)?'r':'-';
    buf[5] = (sbuf.st_mode& S_IWGRP)?'w':'-';
    buf[6] = (sbuf.st_mode& S_IXGRP)?'x':'-';

    buf[7] = (sbuf.st_mode& S_IROTH)?'r':'-';
    buf[8] = (sbuf.st_mode& S_IWOTH)?'w':'-';
    buf[9] = (sbuf.st_mode& S_IXOTH)?'x':'-';

    char *p = malloc(100);
    if(!p){
        perror("p");
        exit(1);
    }
    memset(p,0,100);
    memcpy(p,ctime(&sbuf.st_ctime),strlen(ctime(&sbuf.st_ctime))-1);
    printf ("%s %lu %s %s %lu %s %s",buf,sbuf.st_nlink,getpwuid(sbuf.st_uid)->pw_name,getgrgid(sbuf.st_gid)->gr_name,sbuf.st_size,p,path);
    free(p);
    if(buf[0]=='l'){
        char b[100];
        memset(b,0,sizeof(b));
        readlink(path,b,sizeof(b));
        printf("->%s",b);
    }
    putchar('\n');

    return 0;
}
bool isDir(const char *p)
{
    if(!p){
        perror("open error");
        exit(1);
    }
    struct stat sbuf;
    stat(p,&sbuf);
    return S_ISDIR(sbuf.st_mode);
}
int myls(const char *p)
{
    if(!p){
ERROR:
        perror("open error");
        exit(1);
    }
#define BUF_SIZE   1000
    char buf[BUF_SIZE];

    memset(buf,0,BUF_SIZE);

    if(isDir(p)){
        //printf("\npath=%s\n",p);
        DIR *dp =opendir(p);
        if(!dp){
            goto ERROR;
        }
        struct dirent *d ;
        while( (d= readdir(dp))){
            if((d->d_name[0] == d->d_name[1] && d->d_name[0] =='.' )
               ||(strlen(d->d_name) == 1 && d->d_name[0] == '.' )
            ){
                //printf("%s\t",d->d_name);
                continue;
            }
            snprintf(buf,BUF_SIZE,"%s/%s",p,d->d_name);
            void show(const char *p);
            show(buf);


        }
    }
    else{
        printf ("%s\t",p);
    }
    return 0;
}
void show(const char *p)
{
    if(!p){
        perror("open error");
        exit(1);
    }
    char buf[BUF_SIZE];
    memset(buf,0,BUF_SIZE);
    if(isDir(p)){
        myls(p);
    }
    fileDetail(p);
    //printf("%s\t",p);
}